package com.jh.fcsm.config;

import com.alibaba.fastjson2.JSONObject;
import com.jh.fcsm.beans.sys.SysUser;
import com.jh.fcsm.beans.sys.vo.LoginUser;
import com.jh.fcsm.beans.sys.vo.ResponseInfo;
import com.jh.fcsm.beans.sys.vo.Token;
import com.jh.fcsm.common.annotation.OperLogAnnotation;
import com.jh.fcsm.constant.TokenConstants;
import com.jh.fcsm.dao.sys.SysUserMapper;
import com.jh.fcsm.service.sys.LoginAttemptService;
import com.jh.fcsm.service.sys.TokenService;
import com.jh.fcsm.util.http.IpUtils;
import com.jh.fcsm.util.http.ResponseUtil;
import com.jh.fcsm.util.security.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * spring security处理器
 */
@Configuration
public class SecurityHandlerConfig {

    @Autowired
    private TokenService tokenService;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private LoginAttemptService loginAttemptService;

    /**
     * 登陆成功，返回Token
     *
     * @return
     */
    @Bean
    public AuthenticationSuccessHandler loginSuccessHandler() {
        return new AuthenticationSuccessHandler() {

            @Override
            @OperLogAnnotation(value = "'登录成功'", module = "用户登录", submodule = "用户登录")
            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
                loginAttemptService.loginSucceeded(IpUtils.getIpAddr(request));
                LoginUser loginUser = (LoginUser) authentication.getPrincipal();
                loginUser.setPassword(null);
                Token token = tokenService.saveToken(loginUser);
                loginUser.setToken(token.getToken());

                SysUser user = new SysUser();
                user.setId(loginUser.getId());
                user.setLastLogin(new Date());
                sysUserMapper.updateByPrimaryKeySelective(user);
                JSONObject tokenJson= JSONObject.parseObject(JSONObject.toJSONString(token));

                // Jwt存储信息
                Map<String, Object> claimsMap = new HashMap<String, Object>();
                claimsMap.put(TokenConstants.USER_KEY, token.getToken());
                claimsMap.put(TokenConstants.DETAILS_USER_ID, loginUser.getId());
                claimsMap.put(TokenConstants.DETAILS_USERNAME, loginUser.getUsername());
                claimsMap.put(TokenConstants.DETAILS_USERNICKNAME, loginUser.getNickname());
                claimsMap.put(TokenConstants.DETAILS_USERTYPE, loginUser.getType());

                tokenJson.put("token", JwtUtils.createToken(claimsMap));
                ResponseUtil.responseJson(response, HttpStatus.OK.value(), tokenJson);
            }
        };
    }

    /**
     * 登陆失败
     *
     * @return
     */
    @Bean
    public AuthenticationFailureHandler loginFailureHandler() {
        return new AuthenticationFailureHandler() {
            @Override
            public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) {
                loginAttemptService.loginFailed(IpUtils.getIpAddr(request));
                String msg = null;
                if (exception instanceof BadCredentialsException) {
                    if("您的密码复杂度太低请修改密码后登录".equals(exception.getMessage())){
                        msg = "您的密码复杂度太低请修改密码后登录";
                    }else if("请绑定密钥".equals(exception.getMessage())){
                        msg = "请绑定密钥";
                    }else {
                        msg = "用户名或密码错误";
                    }
                } else {
                    msg = exception.getMessage();
                }
                ResponseInfo info = new ResponseInfo(HttpStatus.UNAUTHORIZED.value() + "", msg);
                ResponseUtil.responseJson(response, HttpStatus.UNAUTHORIZED.value(), info);
            }
        };

    }

    /**
     * 未登录，返回401
     *
     * @return
     */
    @Bean
    public AuthenticationEntryPoint authenticationEntryPoint() {
        return new AuthenticationEntryPoint() {

            @Override
            public void commence(HttpServletRequest request, HttpServletResponse response,
                                 AuthenticationException authException) throws IOException, ServletException {
                ResponseInfo info = new ResponseInfo(HttpStatus.UNAUTHORIZED.value() + "", "请先登录");
                ResponseUtil.responseJson(response, HttpStatus.UNAUTHORIZED.value(), info);
            }
        };
    }

    /**
     * 退出处理
     *
     * @return
     */
    @Bean
    public LogoutSuccessHandler logoutSussHandler() {
        return new LogoutSuccessHandler() {

            @Override
            public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {
                ResponseInfo info = new ResponseInfo(HttpStatus.OK.value() + "", "退出成功");

                String token = tokenService.getToken(request);
                tokenService.deleteToken(token);

                ResponseUtil.responseJson(response, HttpStatus.OK.value(), info);
            }
        };

    }

}
